home *** CD-ROM | disk | FTP | other *** search
/ Software Vault: The Gold Collection / Software Vault - The Gold Collection (American Databankers) (1993).ISO / cdr49 / 288_01.zip / MSTR_ENV.C < prev    next >
Text File  |  1993-04-01  |  9KB  |  339 lines

  1. /*========================================================================
  2.     Module:   Mstr_Env (Master Environment Access)
  3.     Version:  1.00     11-Mar-1989
  4.  
  5.     Written by Scott Robert Ladd.
  6.  
  7.     This software has been released into the public domain;
  8.     no warranties are expressed or implied.
  9.  
  10.     This source code will work with most MS-DOS C compilers. It has been
  11.     tested with Microsoft C 5.1 and QuickC 2.0, Borland Turbo C 2.0, and
  12.     Zortech C v1.07.
  13. =========================================================================*/
  14.  
  15. #include "dos.h"      /* _psp definition */
  16. #include "stddef.h"   /* NULL and other standard definitions */
  17. #include "string.h"   /* string functions */
  18. #include "mstr_env.h" /* to get prototypes */
  19.  
  20. /* define a macro for MSC and QC */
  21. #if defined(_QC) || defined (_MSC)
  22.      #define MK_FP(seg,off) ((void far *)(((long)(seg) << 16L) | (long)(off)))
  23. #endif
  24.  
  25. /*
  26. internal MS-DOS structures
  27. --------------------------
  28. */
  29.  
  30. typedef struct
  31.     {
  32.     char reserved1[22];
  33.     unsigned par_seg;   /* segment of the parent of the current program */
  34.     char reserved2[20];
  35.     unsigned env_seg;   /* environment segment for current program */
  36.     }
  37.     PSP;
  38.  
  39.   /*-----------------
  40.      IMPORTANT NOTE!
  41.     -----------------------------------------------------------------------
  42.      The MCB structure must be compiled with byte, not word, alignment. In
  43.      Microsoft C, this is accomplished through the use of the pack pragma.
  44.      By default, Turbo C uses byte alignment. When compiling this module
  45.      with Zortech C, the -a switch must be used to get byte alignment.
  46.     ----------------------------------------------------------------------- */
  47.  
  48. #if defined(_QC) || defined(_MSC)
  49.     #pragma pack(1)
  50. #endif
  51.  
  52. typedef struct
  53.     {
  54.     char status;         /* indicates whether this block is in chain */
  55.     unsigned owner_PSP;  /* the PSP segment of this block's owner */
  56.     unsigned len;        /* the size (in paragraphs) of this memory block */
  57.     }
  58.     MCB;
  59.  
  60. #if defined(_QC) || defined(_MSC)
  61.     #pragma pack()
  62. #endif
  63.  
  64. /*
  65. global declarations
  66. -------------------
  67. */
  68.  
  69. char far * env_ptr; /* pointer to first byte of global env. */
  70. static unsigned   env_len; /* length of global environment */
  71.  
  72. static int initialized = 0; /* indicates whether the module is initialized */
  73.  
  74. static char s[256];         /* internal buffer used for strings */
  75.  
  76. static void m_findenv(void); /* internal function used to find the master
  77.                                 environment */
  78.  
  79. #define NUL '\x00' /* the nul (zero) character used by C as a string
  80.                       terminator */
  81.  
  82. /*
  83. function definitions
  84. --------------------
  85. */
  86.  
  87. /*
  88.   function:     m_getenv
  89.  
  90.   purpose:      retrieves an environment variable's value
  91.  
  92.   parameters:   name -- the name of the variable whose value is sought
  93.  
  94.   returns:      A pointer to the value of the requested variable, or NULL if the
  95.                 variable was not found.
  96.  
  97.                 NOTE: the return value is a pointer to a static char array in
  98.                 this module. Thus the previous value is destroyed each time this
  99.                 function is called.
  100. */
  101.  
  102. char * m_getenv(char * name)
  103.     {
  104.     char far * e;
  105.     char *     n;
  106.     int        i;
  107.  
  108.     /* check for initialization */
  109.     if (!initialized)
  110.          m_findenv();
  111.  
  112.     e = env_ptr;
  113.  
  114.     /* search for name */
  115.     while (*e)
  116.         {
  117.         n = name;
  118.  
  119.         while ((*e == *n) && (*e != '=') && (*e != NUL) && (*n != NUL))
  120.             {
  121.             ++e;
  122.             ++n;
  123.             }
  124.  
  125.         if ((*n == NUL) && (*e == '=')) /* name found */
  126.              {
  127.              /* copy variable value to s */
  128.              ++e;
  129.  
  130.              /* strcpy() cannot be used because pointer sizes may differ */
  131.              for (i = 0; (i < 256) && (*e != NUL); ++i)
  132.                   {
  133.                   s[i] = *e;
  134.                   ++e;
  135.                   }
  136.  
  137.              if (i < 256)
  138.                  s[i] = NUL;
  139.  
  140.              return s; /* contains value of name */
  141.              }
  142.  
  143.         /* skip to the next environment variable */
  144.         while (*e != NUL)
  145.             ++e;
  146.  
  147.         ++e;
  148.         }
  149.  
  150.     /* name wasn't found */
  151.     return NULL;
  152.     }
  153.  
  154. /*
  155.     function:   m_putenv
  156.  
  157.     purpose:    stores an environment variable
  158.  
  159.     parameters: name -- name of the variable to be stored
  160.                 text -- the variable's value
  161.  
  162.     returns:    0 if the variable was stored
  163.                 1 if not
  164. */
  165.  
  166. int m_putenv(char *name, char *text)
  167.     {
  168.     char far * e;
  169.     unsigned   l = 0;
  170.     char *     sptr;
  171.  
  172.     /* check for initialization */
  173.     if (!initialized)
  174.          m_findenv();
  175.  
  176.     e = env_ptr;
  177.  
  178.     /* check to see that the storage required is < 256 bytes */
  179.     if ((strlen(name) + 2 + strlen(text)) > 256)
  180.         return 1;
  181.  
  182.     /* make a complete environment string from the components given */
  183.     strcpy(s,name);
  184.     strupr(s);
  185.     strcat(s,"=");
  186.     strcat(s,text);
  187.  
  188.     /* delete any existing variables of the same name */
  189.     m_delenv(name);
  190.  
  191.     /* find the end of the current variables (mark by two nulls) */
  192.     e = env_ptr;
  193.     l = 0;
  194.  
  195.     /* loop until two NULs are found, signifying the end of the environment */
  196.     while (!((*e == NUL) && (*(e+1) == NUL)))
  197.         {
  198.         ++e;
  199.         ++l;
  200.         }
  201.  
  202.     /* get the amount of remaining space */
  203.     l = env_len - l - 1;
  204.  
  205.     /* if the new variable won't fit, return an error */
  206.     if (l < strlen(s))
  207.          return 1;
  208.  
  209.     sptr = s;
  210.  
  211.     /* otherwise, copy s onto the end of the current environment */
  212.     ++e;
  213.  
  214.     while (*sptr != NUL)
  215.         *e++ = *sptr++;
  216.  
  217.     /* end the environment with two NUL bytes */
  218.     *e = NUL;
  219.     *(e + 1) = NUL;
  220.  
  221.     /* it worked! */
  222.     return 0;
  223.     }
  224.  
  225. /*
  226.     function:   m_delgenv
  227.  
  228.     purpose:    deletes an environment variable
  229.  
  230.     parameters: name -- the name of the variable to be deleted
  231.  
  232.     returns:    1 if the variable could not be deleted or does not exit
  233.                 0 upon success
  234. */
  235. int m_delenv(char *name)
  236.      {
  237.     char far * e1; /* used in search & marks beginning of next variable */
  238.     char far * e2; /* marks beginning of the variable */
  239.     char * n;      /* name pointer used in search */
  240.     int searching = 1; /* flag to indicate search end */
  241.  
  242.     /* has the module been initialized? If not, do it! */
  243.     if (!initialized)
  244.         m_findenv();
  245.  
  246.     e1 = env_ptr;
  247.  
  248.     /* find the beginning of the variable to be deleted */
  249.     while ((*e1 != NUL) && (searching))
  250.         {
  251.         n  = name;
  252.         e2 = e1;
  253.  
  254.         while ((*e1 == *n) && (*e1 != '=') && (*e1 != NUL) && (*n != NUL))
  255.             {
  256.             ++e1;
  257.             ++n;
  258.             }
  259.  
  260.         if ((!*n) && (*e1 == '='))
  261.             searching = 0; /* the variable we want was found! */
  262.  
  263.         while (*e1 != NUL)
  264.             ++e1;
  265.  
  266.         ++e1;
  267.         }
  268.  
  269.     /* if name wasn't found, return with an error */
  270.     if ((*e1 == NUL) && (searching))
  271.          return 1;
  272.  
  273.     /* otherwise, copy the remainder of the environment over name */
  274.     while (!((*e1 == NUL) && (*(e1+1) == NUL)))
  275.         {
  276.         *e2 = *e1;
  277.         e2++;
  278.         e1++;
  279.         }
  280.  
  281.     /* end the environment with double NUL bytes */
  282.     *e2 = NUL;
  283.     *(e2 + 1) = NUL;
  284.  
  285.     /* it worked */
  286.     return 0;
  287.     }
  288.  
  289. /*
  290.     function:   m_findenv
  291.  
  292.     purpose:    locates the global environment and sets a pointer to it
  293.  
  294.     parameters: none
  295.  
  296.     returns:    nothing
  297. */
  298.  
  299. static void m_findenv()
  300.     {
  301.     union  REGS  regs;
  302.     struct SREGS sregs;
  303.     int far * SEGptr;    /* set to address of segment of first MCB */
  304.     MCB far * CONFIGmcb; /* set to address of CONFIG's MCB */
  305.     MCB far * SHELLmcb;  /* set to address of COMMAND.COM's MCB */
  306.     MCB far * ENVmcb;    /* set to address of environment's MCB */
  307.     PSP far * SHELLpsp;  /* set to address of COMMAND.COM's PSP */
  308.  
  309.     regs.h.ah = 0x52;
  310.     intdosx(®s,®s,&sregs);
  311.  
  312.     SEGptr = MK_FP(sregs.es, regs.x.bx - 2);
  313.  
  314.     CONFIGmcb = MK_FP(*SEGptr,0);
  315.  
  316.     SHELLpsp = MK_FP(FP_SEG(CONFIGmcb) + CONFIGmcb->len + 2, 0);
  317.  
  318.     if (SHELLpsp->env_seg == 0)
  319.         {
  320.         /* the environment is in the block AFTER the parent program */
  321.         SHELLmcb = MK_FP(FP_SEG(CONFIGmcb) + CONFIGmcb->len + 1, 0);
  322.         env_ptr  = MK_FP(FP_SEG(SHELLmcb)  + SHELLmcb->len  + 2, 0);
  323.         }
  324.     else
  325.         {
  326.         /* otherwise, we have a direct pointer to the environment block */
  327.         env_ptr = MK_FP(SHELLpsp->env_seg, 0);
  328.         }
  329.  
  330.     /* set a ppointer to the MCB of the environment block */
  331.     ENVmcb = MK_FP(FP_SEG(env_ptr) - 1, 0);
  332.  
  333.     /* calculate the length of the environment */
  334.     env_len = ENVmcb->len * 16;
  335.  
  336.     /* set the initialization flag */
  337.     initialized = 1;
  338.     }
  339.